// using Godot;
// using System;

// using ll = System.Int64;
// using ld = System.Double;




// public partial class TimeSystem : Node
// {
//     enum Season
//     {
//         SPRING = 0,
//         SUMMER,
//         AUTUMN,
//         WINTER
//     }




//     // declare signals
//     [Signal]
//     public delegate void MinutePassedEventHandler();
//     [Signal]
//     public delegate void HourPassedEventHandler();
//     [Signal]
//     public delegate void DayPassedEventHandler();


//     [Export] public ll TimeScale { get; set; } = 72; // 1 real second = 60 in-game seconds

//     [Export] private ll accumulatedTime { get; set; } = 0;
//     [Export] private ll currentDay { get; set; } = 1;
//     [Export] private Season currentSeason { get; set; } = Season.AUTUMN;

//     public override void _Process(ld delta)
//     {
//         accumulatedTime += (ll)(delta * TimeScale);


//         if (accumulatedTime % 60 == 0)
//             EmitSignal(SignalName.MinutePassed);

//         if (accumulatedTime % 3600 == 0)
//             EmitSignal(SignalName.HourPassed);
//         if (accumulatedTime % 86400 == 0)
//         {
//             currentDay += 1;
//             EmitSignal(SignalName.DayPassed);
//         }


//         GD.Print(GetCurrentTimeString());
//     }


//     public string GetCurrentTimeString()
//     {
//         ll totalSeconds = accumulatedTime;
//         ll hours = (totalSeconds / 3600) % 24;
//         ll minutes = (totalSeconds / 60) % 60;

//         // return $"{hours:D2}:{minutes:D2}";
//         return string.Format("Day {0} - {1:D2}:{2:D2}", currentDay, hours, minutes);
//     }








// }




using Godot;
using System;

// 使用别名方便后续修改
using ll = System.Int64; // long
using ld = System.Double; // double

public partial class TimeSystem : Node
{
    public enum Season
    {
        SPRING = 0,
        SUMMER,
        AUTUMN,
        WINTER
    }

    // 信号声明
    [Signal]
    public delegate void MinutePassedEventHandler();
    [Signal]
    public delegate void HourPassedEventHandler();
    [Signal]
    public delegate void DayPassedEventHandler();

    // 导出变量
    [Export] public double TimeScale { get; set; } = 72.0; // 改用 double 避免精度丢失

    // 不再直接 Export accumulatedTime 让外部修改，而是作为计算结果
    // 假如你想从存档加载时间，修改这个变量即可（代表游戏开始时的初始秒数）
    [Export] public double InitialInGameSeconds { get; set; } = 0;

    // 内部变量：记录游戏启动时的系统时间（毫秒）
    private ulong _appStartTicks;

    // 用于记录上一次检测时的分钟/小时/天，用来触发信号
    private ll _lastTotalMinutes = -1;
    private ll _lastTotalHours = -1;
    private ll _lastTotalDays = -1;

    public override void _Ready()
    {
        // 记录节点初始化时的系统时间
        _appStartTicks = Time.GetTicksMsec();

        // 初始化追踪器，防止刚启动时疯狂触发信号
        double startSeconds = GetCurrentTotalGameSeconds();
        _lastTotalMinutes = (ll)(startSeconds / 60);
        _lastTotalHours = (ll)(startSeconds / 3600);
        _lastTotalDays = (ll)(startSeconds / 86400);
    }

    public override void _Process(double delta)
    {
        // 1. 获取当前总游戏时间（秒）
        // 算法：初始时间 + ( (当前系统时间 - 启动系统时间) * 倍率 )
        double currentTotalGameSeconds = GetCurrentTotalGameSeconds();
        ll currentSecondsInt = (ll)currentTotalGameSeconds;

        // 2. 检测时间流逝并触发信号
        // 我们比较“现在的时间”和“上一帧记录的时间”

        // --- 分钟检测 ---
        ll currentTotalMinutes = currentSecondsInt / 60;
        if (currentTotalMinutes > _lastTotalMinutes)
        {
            // 这里用 while 是为了防止：如果游戏卡了很久（或者最小化很久），
            // 突然回来，时间跳过了很多分钟，我们需要决定是触发一次还是多次。
            // 通常为了性能和逻辑简单，我们只触发一次“时间变了”，
            // 但这里我写成触发一次信号，代表“新的一分钟到了”。
            _lastTotalMinutes = currentTotalMinutes;
            EmitSignal(SignalName.MinutePassed);
        }

        // --- 小时检测 ---
        ll currentTotalHours = currentSecondsInt / 3600;
        if (currentTotalHours > _lastTotalHours)
        {
            _lastTotalHours = currentTotalHours;
            EmitSignal(SignalName.HourPassed);
        }

        // --- 天数检测 ---
        ll currentTotalDays = currentSecondsInt / 86400;
        if (currentTotalDays > _lastTotalDays)
        {
            _lastTotalDays = currentTotalDays;
            EmitSignal(SignalName.DayPassed);
        }

        // 打印调试（可选，正式版建议移除或用 UI 显示）
        // GD.Print(GetCurrentTimeString());
    }

    /// <summary>
    /// 获取当前游戏累计流逝的总秒数（精确到小数）
    /// </summary>
    public double GetCurrentTotalGameSeconds()
    {
        ulong currentTicks = Time.GetTicksMsec();
        // 计算从游戏启动到现在经过了多少现实秒
        double realSecondsPassed = (currentTicks - _appStartTicks) / 1000.0;

        // 转换为游戏内秒数
        return InitialInGameSeconds + (realSecondsPassed * TimeScale);
    }

    // 获取当前是第几天 (从 Day 1 开始)
    public ll GetCurrentDay()
    {
        return ((ll)GetCurrentTotalGameSeconds() / 86400) + 1;
    }

    // 根据天数计算季节 (假设每个季节 30 天)
    public Season GetCurrentSeason()
    {
        ll day = GetCurrentDay();
        // 这里的算法是演示用的：每30天换个季，循环
        // (day - 1) 是为了让 Day 1 对应索引 0
        int seasonIndex = (int)(((day - 1) / 30) % 4);
        return (Season)seasonIndex;
    }

    public string GetCurrentTimeString()
    {
        ll totalSeconds = (ll)GetCurrentTotalGameSeconds();

        // 计算当天内的时间
        ll secondsInDay = totalSeconds % 86400;
        ll hours = secondsInDay / 3600;
        ll minutes = (secondsInDay % 3600) / 60;

        // 获取天数和季节
        ll currentDay = GetCurrentDay();
        Season currentSeason = GetCurrentSeason();

        return string.Format("Day {0} ({1}) - {2:D2}:{3:D2}", currentDay, currentSeason, hours, minutes);
    }
}